/**
 * @desc 基于axios对请求的公共封装
 * 使用方式同axios
 * method:POST,参数放置data字段中
 * method:GET,参数放置params字段中
 * 自定义拦截
 *    hideLoading    是否隐藏loading
 *    cancelRepeat   前一次请求没响应时，又触发一次请求，此时是否取消重复请求
 */
import axios from 'axios';
import QS from 'query-string';
import { notification } from 'antd';
import loading from './Loading/index';

const token = '12345';

const getDataType = (data: any): string => {
  return Object.prototype.toString.call(data).slice(1, -1).split(' ')[1];
}

/** @desc 取消连续请求 */
const { CancelToken } = axios;
const cacheRequest: any = {};

/** @desc 辅助工具函数 */
const axiosTool = {
  throwError: (responseData: any) => {
    let msg = '';
    if (+responseData.code !== 0 || !responseData.success) {
      switch (responseData.code) {
        case '10001':
          msg = '登录超时,请重新登录';
          break;
        case 'PARAM_MISS':
          msg = '参数缺失';
          break;
        default:
          msg = responseData.msg;
      }
      notification.error({
        message: msg || responseData.msg || responseData.ErrorMessage || '后端接口返回数据为空',
      });
    }
  },
  throwHttpError: (err: any) => {
    let msg = '';
    let tip = '';
    if (err.response && err.response.status) {
      tip = err.response.config.url;
      switch (+err.response.status) {
        case 400:
          msg = `请求错误（${err.response.status}）:`;
          break;
        case 403:
          msg = `请求被拒绝（${err.response.status}）:`;
          break;
        case 404:
          msg = `请求地址出错（${err.response.status}）:`;
          break;
        case 408:
          msg = `服务器超时（${err.response.status}）:`;
          break;
        case 500:
          msg = `服务器错误（${err.response.status}）:`;
          break;
        case 501:
          msg = `请求方式错误（${err.response.status}）:`;
          break;
        case 502:
          msg = `网关错误（${err.response.status}）:`;
          break;
        case 504:
          msg = `网关超时（${err.response.status}）:`;
          break;
        default:
          msg = '';
      }
    } else if (err.code === 'ECONNABORTED' && err.message.indexOf('timeout') !== -1) {
      msg = '网络连接超时，请稍后重试';
    } else if (err.message === 'Network Error') {
      msg = '网络链接有误';
      tip = '请检查网络连接';
    }
    notification.error({
      message: msg,
      description: tip || '',
    });
  },
};

/** @desc 默认配置 */
const axiosConfig = {
  headers: {
    post: {
      'Content-Type': 'application/json;charset=UTF-8',
    },
  },
  transformRequest: (data: any) => {
    if (getDataType(data) === 'Object') {
      return QS.stringify(data);
    }
    return data;
  },
};

/** @desc 请求拦截器 */
const requestInterceptors = {
  success: (config: any) => {
    const newConfig: T.stringAnyObj = { ...config };
    if (!config.timeout) {
      newConfig.timeout = 10000;
    }
    // 集中处理 post json
    if (
      config.method === 'post' &&
      (config.headers['Content-Type'] || config.headers.post['Content-Type']) === 'application/json;charset=UTF-8'
    ) {
      typeof config.data !== 'string' && (newConfig.data = JSON.stringify(config.data));
    }
    // 是否隐藏loading
    !(config && config.headers?.hideLoading) && loading.show();
    // 此处存放token，所有请求头均会带上对应的token信息
    newConfig.headers['Souche-Inc-Security-Token'] = token;
    newConfig.headers['Souche-Security-Token'] = token;
    newConfig.headers['souche-security-token-inc'] = token;
    newConfig.url = config.url;
    // 取消连续请求
    const cacheUrl = `${config.baseURL}${config.url}`;
    if (cacheRequest[cacheUrl]) {
      if (config.cancelRepeat) {
        cacheRequest[cacheUrl]('取消啦');
        delete cacheRequest[cacheUrl];
      } else {
        delete cacheRequest[cacheUrl];
      }
    }
    newConfig.cancelToken = new CancelToken((cancel) => {
      cacheRequest[cacheUrl] = cancel;
    });

    return { ...config, ...newConfig };
  },
  error: (error: any) => Promise.reject(error),
};

/** @desc 响应拦截器 */
const responseInterceptors = {
  success: (response: any) => {
    const { config } = response;
    !(config && config.headers?.hideLoading) && loading.hide();
    if (config.responseType === 'blob') {
      return response.data;
    }
    const responseData = response.data || {};
    if (responseData.code !== 0) {
      axiosTool.throwError(responseData);
      return Promise.reject(responseData);
    }
    const cacheUrl = `${config.baseURL}${config.url}`;
    if (cacheRequest[cacheUrl]) {
      delete cacheRequest[cacheUrl];
    }
    return responseData.data === 'undefined' ? responseData : responseData.data;
  },
  error: (err: any) => {
    const { config } = err;
    if (config) {
      !(config && config.hideLoading) && loading.hide();
      !config.cancelRepeat && axiosTool.throwHttpError(err);
      return Promise.reject(err.response.data || {});
    }
    return Promise.reject(err || {});
  },
};

/** @desc 对外抛出函数，用以创建axios实例 */
const createHttpInstance = (changeConfig: { baseURL: string; [key: string]: any }, request = true, response = true) => {
  const customAxios = axios.create({ ...axiosConfig, ...changeConfig });
  request && customAxios.interceptors.request.use(requestInterceptors.success, requestInterceptors.error);
  response && customAxios.interceptors.response.use(responseInterceptors.success, responseInterceptors.error);
  return customAxios;
};

export default createHttpInstance;
